﻿using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Security;
using System.Threading;
using System.Web.Security;
using System.Xml.Serialization;

namespace dasBlog.Storage
{
    [DataContract(Namespace = Names.DataContractNamespace)]
    internal sealed class SimpleAuthenticationHeader
    {
        [DataMember]
        public string UserName;
        [DataMember]
        public string Password;
    }

    public sealed class SimpleAuthenticationBehavior : IEndpointBehavior
    {
        #region IEndpointBehavior Members

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            if (endpoint.Binding is BasicHttpBinding &&
                ((BasicHttpBinding)endpoint.Binding).Security.Mode == BasicHttpSecurityMode.None )
            {
                var credentials = endpoint.Behaviors.Find<ClientCredentials>();
                if (credentials != null && credentials.UserName != null && credentials.UserName.UserName != null)
                {
                    clientRuntime.MessageInspectors.Add(new ClientMessageInspector(credentials.UserName));                    
                }
            }
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            if (endpoint.Binding is BasicHttpBinding &&
                ((BasicHttpBinding)endpoint.Binding).Security.Mode == BasicHttpSecurityMode.None)
            {
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new DispatchMessageInspector());
            }
        }

        public void Validate(ServiceEndpoint endpoint)
        {
            
        }

        #endregion

        class DispatchMessageInspector : IDispatchMessageInspector
        {
            #region IDispatchMessageInspector Members

            public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                int headerIndex = request.Headers.FindHeader("simpleAuthenticationHeader", "http://dasblog.info/2007/08/security");
                if (headerIndex >= 0)
                {
                    var header = request.Headers.GetHeader<SimpleAuthenticationHeader>(headerIndex);
                    request.Headers.RemoveAt(headerIndex);
                    if ( Membership.ValidateUser(header.UserName, header.Password) )
                    {
                        var identity = new FormsIdentity(new FormsAuthenticationTicket(header.UserName, false, 15));
                        Thread.CurrentPrincipal = new RolePrincipal(identity);
                    }
                }
                return null;
            }

            public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
                
            }

            #endregion
        }

        class ClientMessageInspector : IClientMessageInspector
        {
            #region IClientMessageInspector Members

            UserNamePasswordClientCredential creds;

            public ClientMessageInspector(UserNamePasswordClientCredential creds)
            {
                this.creds = creds;
            }

            public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
                
            }

            public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
            {
                request.Headers.Add(MessageHeader.CreateHeader("simpleAuthenticationHeader", "http://dasblog.info/2007/08/security", new SimpleAuthenticationHeader{ UserName = creds.UserName, Password = creds.Password }));
                return null;
            }

            #endregion
        }
    }

    
}
